package edu.udel.mboch.towerdefense;

import java.util.ArrayList;

public class BattleAIPlayer extends Player implements Actor
{

	private static final long serialVersionUID = 4065702110489300929L;
	private int spawnedMobs;
	
	public BattleAIPlayer(String name)
	{
		super(name);
		spawnedMobs = 0;
	}
	
	public BattleAIPlayer(String name, int cash, int income, int lives, ArrayList<Tower> towers, int spawnedMobs)
	{
		super(name, cash, income, lives, towers);
		this.spawnedMobs = spawnedMobs;
	}
	
	public int getSpawnedMobs()
	{
		return spawnedMobs;
	}
	public ArrayList<TDMove> getAllValidMoves(TDState state)
	{
		BattleTDState battleState = (BattleTDState)state;
		ArrayList<TDMove> moves = new ArrayList<TDMove>();
		int yMin = 0;
		int yMax = Grid.MAX_Y/2;
		if(battleState.getPlayer2().equals(this))
		{
			yMin = Grid.MAX_Y/2;
			yMax = Grid.MAX_Y;
		}
		for(int i = yMin; i<yMax; i++)
			for(int j = 0; j<Grid.MAX_X; j++)
				if(cash>=Tower.BASIC_COST)
				{
					BattleTDState copy = battleState.copy();
					PlayerBuildMove move = new PlayerBuildMove(new BasicTower(new Position(j,i)));
					if(move.isValid(copy))
						moves.add(move);
				}
		if(cash>=Mob.BASIC_COST)
		{
			BattleTDState copy = battleState.copy();
			PlayerSpawnMove move;
			if(state.getPlayer().equals(this))
				move = new PlayerSpawnMove(new BasicMob(new FloatingPosition(battleState.getGrid().getSpawn2().x(), battleState.getGrid().getSpawn2().y()), battleState.getGrid().getPath2(), battleState.getPlayer2()));
			else
				move = new PlayerSpawnMove(new BasicMob(new FloatingPosition(battleState.getGrid().getSpawn().x(), battleState.getGrid().getSpawn().y()), battleState.getGrid().getPath(), battleState.getPlayer()));
			if(move.isValid(copy))
				moves.add(move);
		}
		if(cash>=Mob.FAST_COST)
		{
			BattleTDState copy = battleState.copy();
			PlayerSpawnMove move;
			if(state.getPlayer().equals(this))
				move = new PlayerSpawnMove(new FastMob(new FloatingPosition(battleState.getGrid().getSpawn2().x(), battleState.getGrid().getSpawn2().y()), battleState.getGrid().getPath2(), battleState.getPlayer2()));
			else
				move = new PlayerSpawnMove(new FastMob(new FloatingPosition(battleState.getGrid().getSpawn().x(), battleState.getGrid().getSpawn().y()), battleState.getGrid().getPath(), battleState.getPlayer()));
			if(move.isValid(copy))
				moves.add(move);
		}
		
		return moves;
	}
	
	public TDMove getNextMove(TDState state)
	{
		int maxScore = Integer.MIN_VALUE;
		ArrayList<TDMove> possibleMoves = new ArrayList<TDMove>();
		ArrayList<TDMove> validMoves = getAllValidMoves(state);
		for(TDMove move : validMoves)
		{
			BattleTDState copy = ((BattleTDState)state).copy();
			Player player = copy.getPlayer2();
			if(state.getPlayer().equals(this))
				player = copy.getPlayer();
			move.make(copy);
			if(move instanceof PlayerBuildMove)
			{
				player.getTowers().add(((PlayerBuildMove)move).getTower());				
			}
			if(move instanceof PlayerSpawnMove)
				player.addIncome(((PlayerSpawnMove)move).getMob().getIncome());
			int score = player.getHeuristicScore(copy);
			if(score>maxScore)
				possibleMoves.clear();
			if(score>=maxScore)
			{
				possibleMoves.add(move);
				maxScore = score;
			}
		}
		if(possibleMoves.size() > 0)
		{
			TDMove move = possibleMoves.get((int)(Math.random()*possibleMoves.size()));
			System.out.println(move instanceof PlayerBuildMove);
			if(move instanceof PlayerBuildMove)
				cash -= ((PlayerBuildMove)move).getTower().getCost();
			if(move instanceof PlayerSpawnMove)
			{
				spawnedMobs++;
				income += ((PlayerSpawnMove)move).getMob().getIncome();
				cash -= ((PlayerSpawnMove)move).getMob().getCost();
			}
			return move;
		}
		return null;
	}

	public int getHeuristicScore(TDState state)
	{
		int score = 0;
		for(Tower t : towers)
		{
			int gridCovered = 0;
			for(Position p : t.getPositionsInRange())
			{
				if(!state.getGrid().getTerrain()[p.y()][p.x()].isBuildable())
					gridCovered++;
			}
			score += gridCovered*t.getCost();
		}
		score += income*100;
		return score;
	}
	
	public BattleAIPlayer copy()
	{
		ArrayList<Tower> towersCopy = new ArrayList<Tower>();
		for(Tower t : towers)
			towersCopy.add(t.copy());
			
		return new BattleAIPlayer(name, cash, income, lives, towersCopy, spawnedMobs);
	}
	
	public boolean equals(Object other)
	{
		BattleAIPlayer player = (BattleAIPlayer)other;
		return income == player.getIncome() && cash == player.getCash() && name.equals(player.getName()) && lives == player.getLives();
		
		
	}
}
